/* Copyright (C) 2014-2016 Dan Chapman <dpniel@ubuntu.com>

   This file is part of Dekko email client for Ubuntu Devices/

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of
   the License or (at your option) version 3

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "AttachmentDownloader.h"
#include <QDir>
#include "Imap/Model/Model.h"
#include "Imap/Network/FileDownloadManager.h"
#include <QDebug>

namespace Dekko {

namespace Utils {

AttachmentDownloader::AttachmentDownloader(QObject *parent, const QModelIndex &index)
    : QObject(parent), m_partIndex(index), m_tmpFile(0), m_msgPart(0)
{
}

void AttachmentDownloader::fetchPart()
{
    const Imap::Mailbox::Model *model = 0;
    Imap::Mailbox::Model::realTreeItem(m_partIndex, &model);
    Q_ASSERT(model);

    connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(handleModelDataChanged(QModelIndex,QModelIndex)));
    connect(model, SIGNAL(fileDownloadProgress(qint64, qint64)), this, SIGNAL(downloadProgress(qint64,qint64)));

    m_msgPart = dynamic_cast<Imap::Mailbox::TreeItemPart *>(static_cast<Imap::Mailbox::TreeItem *>(m_partIndex.internalPointer()));
    Q_ASSERT(m_msgPart);
    m_msgPart->fetch(const_cast<Imap::Mailbox::Model *>(model));
    QTimer::singleShot(0, this, SLOT(handleAttachmentDataChanged()));
    if (!m_buffer.isOpen()) {
        m_buffer.setBuffer(m_msgPart->dataPtr());
        m_buffer.open(QIODevice::ReadOnly);
    }
}

void AttachmentDownloader::cleanTmpFile()
{
    delete m_tmpFile;
    m_tmpFile = 0;
}

void AttachmentDownloader::slotFileNameRequestedOnOpen()
{
    Q_ASSERT(!m_tmpFile);
    QString fileName = m_partIndex.data(Imap::Mailbox::RolePartFileName).toString();
    if (fileName.isEmpty()) {

        QString uid = m_partIndex.data(Imap::Mailbox::RoleMessageUid).toString();
        QString partId = m_partIndex.data(Imap::Mailbox::RolePartId).toString();

        if (partId.isEmpty()) {
            // we're saving the complete message
            fileName =  tr("msg_%1.eml").arg(uid);
        } else {
            // it's a message part
            fileName =  tr("msg_%1_%2").arg(uid, partId);
        }
    }
    m_tmpFile = new QTemporaryFile(QDir::tempPath() +
                                   QStringLiteral("/dekko-attachment-XXXXXX-") +
                                   fileName.replace(QLatin1Char('/'), QLatin1Char('_')));
    m_tmpFile->open();

}

void AttachmentDownloader::onOpenFailed(QString)
{
    cleanTmpFile();
    emit error(tr("Download failed."));
}

void AttachmentDownloader::openDownloadedAttachment()
{
    Q_ASSERT(m_tmpFile);
    m_tmpFile->setPermissions(QFile::ReadOwner);
    emit downloadComplete(QUrl::fromLocalFile(m_tmpFile->fileName()).toString());
}

void AttachmentDownloader::handleModelDataChanged(const QModelIndex &topLeft, const QModelIndex &btmRight)
{
    Q_UNUSED(btmRight);
    if (topLeft.model() != m_partIndex.model()) {
        return;
    }
    if (topLeft == m_partIndex) {
        handleAttachmentDataChanged();
    }
}

void AttachmentDownloader::handleAttachmentDataChanged()
{
    if (m_partIndex.data(Imap::Mailbox::RoleIsUnavailable).toBool()) {
        emit error(tr("Offline"));
        return;
    }

    if (!m_partIndex.data(Imap::Mailbox::RoleIsFetched).toBool())
        // probably hasn't arrived yet... return and wait for it.
        return;
    handleAttachmentDataTransfered();
    emit readyRead();
}

void AttachmentDownloader::handleAttachmentDataTransfered()
{
    slotFileNameRequestedOnOpen();
    if (!m_tmpFile->open()) {
        qDebug() << "TMPFILE NOT OPEN";
        emit error(m_tmpFile->errorString());
        return;
    }
    if (m_tmpFile->write(m_buffer.data()) == -1) {
        qDebug() << "Failed writing file";
        emit error(m_tmpFile->errorString());
        return;
    }
    m_tmpFile->close();
    openDownloadedAttachment();
}

}
}
